import 'dart:developer' as nlog;
import 'dart:math';

import 'package:flutter/material.dart';
import 'package:xml/xml.dart';

import '../manager/entity/xf_eval_result_entity.dart';

/// 评测结果工具类 评分标准、得分、评测结果都可以通过这里转换获取
class EvalResultUtils {
  static EvalResultUtils? _instance;

  static EvalResultUtils instance({XFEvalResultEntity? entity}) {
    _instance ??= EvalResultUtils._internal();
    if (entity != null) {
      _newData = entity;
    }
    return _instance!;
  }

  /// 评测结果实体
  static XFEvalResultEntity? _entity;

  static set _newData(XFEvalResultEntity entity) {
    _entity = entity;
    _xmlDocument = null;
  }

  /// 转换后的结果
  static XmlDocument? _xmlDocument;

  String TAG = 'EvalResultUtils';

  EvalResultUtils._internal();

  /// 评测评分标准
  double _STAR_ONE = 40.0;
  double _STAR_TWO = 50.0;
  double _STAR_THREE = 60.0;
  double _STAR_FOUR = 75.0;
  double _STAR_FIVE = 85.0;

  /// 设置评测评分标准
  set setEvalScoreStandard(List<double> standard) {
    if (standard.length != 5) {
      nlog.log('$TAG 传入的评测评分标准数组长度不为5！');
      return;
    }
    _STAR_ONE = standard[0];
    _STAR_TWO = standard[1];
    _STAR_THREE = standard[2];
    _STAR_FOUR = standard[3];
    _STAR_FIVE = standard[4];
  }

  /// 获取评分标准
  List<double> get getEvalScoreStandard =>
      [_STAR_ONE, _STAR_TWO, _STAR_THREE, _STAR_FOUR, _STAR_FIVE];

  /// 获取总得分
  double getScore() {
    if (_entity == null || _entity!.result.isEmpty) {
      nlog.log('$TAG 传入的数据异常!');
      return -1;
    }

    _xmlDocument ??= XmlDocument.parse(_entity!.result);
    String? totalScore;

    /// 获取第一个总得分
    for (var element in _xmlDocument!.descendants) {
      // nlog.log('$TAG 遍历 $element');
      if (element is XmlElement &&
          element.getAttribute('total_score') != null) {
        nlog.log('获取到了分数');
        totalScore = element.getAttribute('total_score');
        break;
      }
    }
    if (totalScore == null) {
      nlog.log('$TAG 获取总分失败！');
      return -1;
    }
    nlog.log('$TAG 总分：$totalScore');
    return double.parse(totalScore);
  }

  /// 获取流畅度评分
  double getFluencyScore() {
    if (_entity == null || _entity!.result.isEmpty) {
      nlog.log('$TAG 传入的数据异常!');
      return -1;
    }
    _xmlDocument ??= XmlDocument.parse(_entity!.result);
    String? fluencyScore;

    /// 获取第一个总得分
    for (var element in _xmlDocument!.descendants) {
      // nlog.log('$TAG 遍历 $element');
      if (element is XmlElement &&
          element.getAttribute('fluency_score') != null) {
        nlog.log('获取到了流畅度分数');
        fluencyScore = element.getAttribute('fluency_score');
        break;
      }
    }
    if (fluencyScore == null) {
      nlog.log('$TAG 获取流畅度总分失败！');
      return -1;
    }
    nlog.log('$TAG 流畅度总分：$fluencyScore');
    return double.parse(fluencyScore);
  }

  /// 获取完整度评分
  double getIntegrityScore() {
    if (_entity == null || _entity!.result.isEmpty) {
      nlog.log('$TAG 传入的数据异常!');
      return -1;
    }
    _xmlDocument ??= XmlDocument.parse(_entity!.result);
    String? integrityScore;

    /// 获取第一个总得分
    for (var element in _xmlDocument!.descendants) {
      // nlog.log('$TAG 遍历 $element');
      if (element is XmlElement &&
          element.getAttribute('integrity_score') != null) {
        nlog.log('获取到了完整度分数');
        integrityScore = element.getAttribute('integrity_score');
        break;
      }
    }
    if (integrityScore == null) {
      nlog.log('$TAG 获取完整度总分失败！');
      return -1;
    }
    nlog.log('$TAG 完整度总分：$integrityScore');
    return double.parse(integrityScore);
  }

  /// 获取准确度评分
  double getAccuracyScore() {
    if (_entity == null || _entity!.result.isEmpty) {
      nlog.log('$TAG 传入的数据异常!');
      return -1;
    }
    _xmlDocument ??= XmlDocument.parse(_entity!.result);
    String? accuracyScore;

    /// 获取第一个总得分
    for (var element in _xmlDocument!.descendants) {
      // nlog.log('$TAG 遍历 $element');
      if (element is XmlElement &&
          element.getAttribute('accuracy_score') != null) {
        nlog.log('获取到了准确度分数');
        accuracyScore = element.getAttribute('accuracy_score');
        break;
      }
    }
    if (accuracyScore == null) {
      nlog.log('$TAG 获取准确度总分失败！');
      return -1;
    }
    nlog.log('$TAG 准确度总分：$accuracyScore');
    return double.parse(accuracyScore);
  }

  /// 获取评测结果组件，富文本
  /// [fontSize] 字体大小
  /// [defaultColor] 默认字体颜色
  List<TextSpan> getResultTextSpan(double fontSize,
      {defaultColor = Colors.black}) {
    List<TextSpan> resultTexts = [];
    if (_entity == null || _entity!.result.isEmpty) {
      nlog.log('$TAG 传入的数据异常!');
      return resultTexts;
    }
    String originText = (_entity!.originText ?? '').toLowerCase();
    if (originText.isEmpty) {
      nlog.log('$TAG 无原文！无法匹配单词！');
      return resultTexts;
    }
    _xmlDocument ??= XmlDocument.parse(_entity!.result);

    /// 当前匹配单词
    String? word = '';
    var wordPhoneCnt = 0;

    /// 第一个单词匹配的下标
    int initWordStartIndex = -1;

    /// 当前匹配单词在原文中的结束位置
    int wordEndIndex = -1;

    /// 下一个单词在原文中的开始位置
    int nextWordStartIndex = 0;

    /// 中间的差值
    int differenceIndex = 0;

    for (var value in _xmlDocument!.descendants) {
      if (value is XmlElement) {
        // nlog.log('遍历结果：$value');
        if (value.name.local == 'word') {
          word = value.getAttribute('content');
          nlog.log(
              'word -> [$word] ,word,length -> ${word?.length} wordEndIndex -> $wordEndIndex');
          wordPhoneCnt = 0;
          if (word != null) {
            var index = originText.indexOf(word, max(wordEndIndex, 0));
            if (index < 0) {
              continue;
            }
            nlog.log('word -> $word , index -> $index');
            if (wordEndIndex >= 0) {
              nextWordStartIndex = index;
              differenceIndex = nextWordStartIndex - wordEndIndex;
            }
            wordEndIndex = max(index, 0) + word.length;
            if (initWordStartIndex == -1) {
              initWordStartIndex = index;
            }
          }
          if (initWordStartIndex != 0) {
            /// 判断第一个单词前面是否有标点符号，如果有则添加
            String sub = originText.substring(0, initWordStartIndex);
            resultTexts.add(
              TextSpan(
                text: sub,
                style: TextStyle(fontSize: fontSize, color: defaultColor),
              ),
            );
            initWordStartIndex = 0;
          }
          if (differenceIndex > 0) {
            String nextSub = originText.substring(
                nextWordStartIndex - differenceIndex, nextWordStartIndex);
            resultTexts.add(
              TextSpan(
                text: nextSub,
                style: TextStyle(fontSize: fontSize, color: defaultColor),
              ),
            );
            differenceIndex = 0;
          }

          /// 英文句子才有 total_score ，中文没有 只能通过 phone 标签去判断声母、韵母等是否发音错误
          var totalScore = value.getAttribute('total_score');
          if (totalScore != null && totalScore.isNotEmpty) {
            resultTexts.add(TextSpan(
              text: word ?? 'null',
              style: TextStyle(
                fontSize: fontSize,
                color: _getWordColor(double.parse(totalScore)),
              ),
            ));
            word = null;
            wordPhoneCnt = 0;
          }
        } else if (value.name.local == 'phone') {
          if (word != null) {
            var recNodeType = value.getAttribute('rec_node_type');
            if (recNodeType == 'paper') {
              var perrMsg = value.getAttribute("perr_msg");
              if (perrMsg == '0') {
                if (wordPhoneCnt < 1) {
                  /// wordPhoneCnt 小于 1 说明这个单词还没有添加到列表
                  resultTexts.add(TextSpan(
                    text: word,
                    style: TextStyle(
                      fontSize: fontSize,
                      color: _getWordColor(_STAR_FOUR),
                    ),
                  ));
                }
                wordPhoneCnt++;
              } else {
                /// 有错误发音，删除上一个添加，改为错误的
                if (wordPhoneCnt > 0) {
                  resultTexts.removeLast();
                }
                resultTexts.add(TextSpan(
                  text: word,
                  style: TextStyle(
                    fontSize: fontSize,
                    color: _getWordColor(_STAR_ONE - 1),
                  ),
                ));
                wordPhoneCnt = 0;
                word = null;
              }
            }
          }
        }
      }
    }
    nlog.log(
        '原文长度：${originText.length},当前最后一个词下标 $wordEndIndex , 截取: ${originText.substring(wordEndIndex)}');
    if (wordEndIndex != originText.length) {
      resultTexts.add(
        TextSpan(
          text: originText.substring(wordEndIndex),
          style: TextStyle(fontSize: fontSize, color: defaultColor),
        ),
      );
    }

    return resultTexts;
  }

  /// 根据得分获取颜色
  Color _getWordColor(double score) {
    if (score >= _STAR_FOUR) {
      return const Color(0xff74D95F);
    } else if (score >= _STAR_ONE) {
      return const Color(0xffFFB604);
    } else {
      return const Color(0xffFF7040);
    }
  }

  List<TextSpan> getResultText(double fontSize, {defaultColor = Colors.black}) {
    List<TextSpan> resultTexts = [];
    if (_entity == null || _entity!.result.isEmpty) {
      nlog.log('$TAG 传入的数据异常!');
      return resultTexts;
    }
    String originText = _entity!.originText ?? '';
    if (originText.isEmpty) {
      nlog.log('$TAG 无原文！无法匹配单词！');
      return resultTexts;
    }
    _xmlDocument ??= XmlDocument.parse(_entity!.result);

    /// 当前匹配单词
    String? word = '';
    var wordPhoneCnt = 0;

    /// 第一个单词匹配的下标
    int initWordStartIndex = -1;

    /// 当前匹配单词在原文中的结束位置
    int wordEndIndex = -1;

    /// 下一个单词在原文中的开始位置
    int nextWordStartIndex = 0;

    /// 中间的差值
    int differenceIndex = 0;

    for (var value in _xmlDocument!.descendants) {
      if (value is XmlElement) {
        if (value.name.local == 'word') {
          word = value.getAttribute('content');
          wordPhoneCnt = 0;
          if (word != null) {
            var index = originText.indexOf(word, max(wordEndIndex, 0));
            if (wordEndIndex >= 0) {
              nextWordStartIndex = index;
              differenceIndex = nextWordStartIndex - wordEndIndex;
            }
            wordEndIndex = index + word.length;
            if (initWordStartIndex == -1) {
              initWordStartIndex = index;
            }
          }
          if (initWordStartIndex != 0) {
            /// 判断第一个单词前面是否有标点符号，如果有则添加
            String sub = originText.substring(0, initWordStartIndex);
            resultTexts.add(
              TextSpan(
                text: sub,
                style: TextStyle(fontSize: fontSize, color: defaultColor),
              ),
            );
            initWordStartIndex = 0;
          }
          if (differenceIndex > 0) {
            String nextSub = originText.substring(
                nextWordStartIndex - differenceIndex, nextWordStartIndex);
            resultTexts.add(
              TextSpan(
                text: nextSub,
                style: TextStyle(fontSize: fontSize, color: defaultColor),
              ),
            );
            differenceIndex = 0;
          }

          /// 英文句子才有 total_score ，中文没有 只能通过 phone 标签去判断声母、韵母等是否发音错误
          var totalScore = value.getAttribute('total_score');
          if (totalScore != null && totalScore.isNotEmpty) {
            resultTexts.add(TextSpan(
              text: word ?? 'null',
              style: TextStyle(
                fontSize: fontSize,
                color: _getWordColor(double.parse(totalScore)),
              ),
            ));
            word = null;
            wordPhoneCnt = 0;
          }
        } else if (value.name.local == 'phone') {
          if (word != null) {
            var recNodeType = value.getAttribute('rec_node_type');
            if (recNodeType == 'paper') {
              var perrMsg = value.getAttribute("perr_msg");
              if (perrMsg == '0') {
                if (wordPhoneCnt < 1) {
                  /// wordPhoneCnt 小于 1 说明这个单词还没有添加到列表
                  resultTexts.add(TextSpan(
                    text: word,
                    style: TextStyle(
                      fontSize: fontSize,
                      color: _getWordColor(_STAR_FOUR),
                    ),
                  ));
                }
                wordPhoneCnt++;
              } else {
                /// 有错误发音，删除上一个添加，改为错误的
                if (wordPhoneCnt > 0) {
                  resultTexts.removeLast();
                }
                resultTexts.add(TextSpan(
                  text: word,
                  style: TextStyle(
                    fontSize: fontSize,
                    color: _getWordColor(_STAR_ONE - 1),
                  ),
                ));
                wordPhoneCnt = 0;
                word = null;
              }
            }
          }
        }
      }
    }
    resultTexts.add(
      TextSpan(
        text: originText.substring(wordEndIndex),
        style: TextStyle(fontSize: fontSize, color: defaultColor),
      ),
    );

    return resultTexts;
  }

  /// 获取评测得分星级
  int getStarCount() {
    var scoreList = getEvalScoreStandard;
    var totalScore = getScore();
    var scoreStar = 0;
    if (totalScore >= scoreList[4]) {
      scoreStar = 5;
    } else if (totalScore >= scoreList[3]) {
      scoreStar = 4;
    } else if (totalScore >= scoreList[2]) {
      scoreStar = 3;
    } else if (totalScore >= scoreList[1]) {
      scoreStar = 2;
    } else if (totalScore >= scoreList[0]) {
      scoreStar = 1;
    } else {
      scoreStar = 0;
    }
    return scoreStar;
  }

  /// 根据分数获取对应的音频文件
  String getAudioName({double? score}) {
    var s = score ?? getScore();
    if (s >= _STAR_FIVE) {
      return "eval_excellent_audio.mp3";
    }
    if (s >= _STAR_FOUR) {
      return "eval_good_audio.mp3";
    }
    if (s >= _STAR_THREE) {
      return "eval_good_audio.mp3";
    }
    if (s >= _STAR_TWO) {
      return "eval_medium_audio.mp3";
    }
    if (s >= _STAR_ONE) {
      return "eval_medium_audio.mp3";
    }
    return "eval_bad_audio.mp3";
  }
}
